package svm;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import exception.SessionDirectoryNotFoundException;

import utils.Logger;
import utils.Utils;
import au.AU;
import au.AU.Label;

public class Testing extends SvmContext {
	
	// Public API
	
	/*
	 * Creates the testing context file
	 * @params: luxandDataFilePath - text file where the testing samples are stored 
	 * 
	 * */
	public Testing(String parentDirPath, List<AU> aus) {
		super(parentDirPath, aus);
		// TODO Auto-generated constructor stub
	}

	/*
	 * Creates testing data file and runs SVM
	 * @params: aus - list of AUs that the testing has to be performed for
	 * 
	 * */
	public void testForAUs(List<AU> aus) {
		for (AU au : aus) {
			
			// Creating pos/neg. training data files
			File testingPositiveDataFile = new File("data/test_positive_"
					+ au.getLabel().toString());
			File testingNegativeDataFile = new File("data/test_negative_"
					+ au.getLabel().toString());
			try {
				if (!testingPositiveDataFile.exists())
					testingPositiveDataFile.createNewFile();
				if (!testingNegativeDataFile.exists())
					testingNegativeDataFile.createNewFile();
				Utils.clearFile(testingPositiveDataFile);
				Utils.clearFile(testingNegativeDataFile);
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			// Adding positive vectors if current AU's label is contained by current row
			for (Session.SessionFrame row : sessionList.get(0).getSessionFrames()) {
				if (row.trainingAuLabels.contains(au.getLabel().toString())) {
					double[] featureVector = au.getFeatureVectorByFacialFeatures(row.points);
					if(featureVector != null) { 
						Utils.writeFile(testingPositiveDataFile, 1, featureVector);
					}
					//Logger.log("Testing " + au.getLabel() + ": adding " + row.fileName + "as positive.");
				}
			}
			
			// Adding negative vectors if current AU's negative labels and current row's AUs have non null intersection
			for (Session.SessionFrame row : sessionList.get(0).getSessionFrames()) {
				List tmp = new ArrayList<String>();
				tmp.addAll(row.trainingAuLabels);
				tmp.retainAll(au.getNegatives());
				if (!tmp.isEmpty() && !row.trainingAuLabels.contains(au.getLabel().toString())) {
					double[] featureVector = au.getFeatureVectorByFacialFeatures(row.points);
					if(featureVector != null) {
						Utils.writeFile(testingNegativeDataFile, 1, featureVector);
					}
					//Logger.log("Testing " + au.getLabel() + ": adding " + row.fileName + "as negative.");
				}
			}
		}

		// Running SVM Predict by AU's optimalized parameters
		for (Label label: AU.Label.values()) {
			String pout = Utils.runCmd("svm-predict " + "data/test_positive_" + label + " data/train_" + label + ".model out");
			String nout = Utils.runCmd("svm-predict " + "data/test_negative_" + label + " data/train_" + label + ".model out");
			if(pout.length() > 0 || nout.length() > 0) Logger.log("testing", "\n========= TESTING POSITIVE " + label + " =========\n");
			if(pout.length() > 0) Logger.log("testing", "*** POSITIVE *** " + pout.split("%")[0] + "%");
			if(nout.length() > 0) Logger.log("testing", "*** NEGATIVE *** " + nout.split("%")[0] + "%");
		}
	}

	@Override
	public void loadLuxandData(HashMap<String, String> keywords) {
		String luxandDataFilePath = parentDir.getAbsolutePath() + "/luxand_data";
		try {
			sessionList.add(new Session(luxandDataFilePath, null, this));
		} catch (SessionDirectoryNotFoundException e) {
		}
	}

}
